/**************************************************************************
* This file is part of Hawkengine.
**
* Hawkengine is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
**
* Hawkengine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
**
* You should have received a copy of the GNU Lesser General Public License
* along with Hawkengine.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#ifndef _RENDER_H_
#define _RENDER_H_

/**************************************************************************
* Dependencies
**************************************************************************/
#include "engine/bounds.h"
#include "engine/color.h"
#include "engine/common.h"
#include "engine/font.h"

/**************************************************************************
* Preprocessing
**************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif

#define MAX_MESSAGE_LENGTH 256
#define MESSAGE_DURATION 2.0
#define MESSAGE_HELP_DURATION 5.0
 
#if defined(USE_CUSTOM_ARRAY_BUFFERS) && !defined(NO_VERTEX_BUFFERS)
#define GL_ARRAY_BUFFER 0x8892
#define GL_STATIC_DRAW 0x88E4
typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage);
extern PFNGLGENBUFFERSARBPROC glGenBuffers;
extern PFNGLBINDBUFFERARBPROC glBindBuffer;
extern PFNGLBUFFERDATAARBPROC glBufferData;
extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffers;
#endif

/**************************************************************************
* Types
**************************************************************************/
typedef struct
{
  char message[MAX_MESSAGE_LENGTH];
  float duration;
} message_task_type;

struct message_task_node;
typedef struct message_task_node message_task_node_type;
struct message_task_node
{
  message_task_type message_task;
  message_task_node_type* next;
};

/**************************************************************************
* Variables
**************************************************************************/
extern UINT render_button_texture;
extern UCHAR render_flash_alpha;
extern float render_modelview_matrix[16];
extern float render_projection_matrix[16];

/**************************************************************************
* Static Variables
**************************************************************************/

/**************************************************************************
* Function Prototypes
**************************************************************************/
int render_add_vertices(int count, float* vertices, float* normals,
                        float* textures, float* colors);
void render_arc(float radius, float radians, BOOL filled);
void render_arc_thick(float radius, float radians, BOOL filled, float thickness);
void render_button(const bounds_type* bounds, const char* text,
                   const color_type* bg_color, const color_type* fg_color);
BOOL render_capture(const bounds_type* bounds, const char* file_name);
void render_change_coordinates(const bounds_type* old_bounds,
                               const bounds_type* new_bounds);
void render_check(const bounds_type* bounds, BOOL ok, BOOL colored);
void render_circle(float radius, BOOL filled);
void render_circle_thick(float radius, BOOL filled, float thickness);
void render_dark_shade(const bounds_type* bounds, UCHAR alpha);
void render_dismiss_message(void);
float render_get_depth_at(float x, float y, const bounds_type* bounds);
void render_init(void);
void render_line(int dimensions, const float* p1, const float* p2);
void render_look_at(const float eye[3], const float look_at[3], const float up[3]);
void render_perspective(float fov, float aspect, float near, float far);
BOOL render_project(float x, float y, float z,
                    const bounds_type* bounds,
                    const float model[16], const float projection[16],
                    float* win_x, float* win_y, float* win_z);
void render_rect(const bounds_type* bounds, BOOL filled);
void render_rect_thick(const bounds_type* bounds, BOOL filled, float thickness);
void render_set_color(const color_type* color);
void render_set_viewport(const bounds_type* bounds);
void render_set_view_ortho(const bounds_type* bounds);
void render_set_view_perspective(const float eye[3],
                                 const float look_at[3],
                                 const float up[3],
                                 float fovy,
                                 float aspect_ratio,
                                 float near_plane,
                                 float far_plane);
void render_set_view_perspective_camera(const camera_type* camera,
                                        float fovy,
                                        float aspect_ratio,
                                        float near_plane,
                                        float far_plane);
void render_show_message(const char* message, float duration);
BOOL render_showing_message(void);
void render_start(const bounds_type* bounds);
void render_stop(const bounds_type* bounds);
void render_texture(const bounds_type* bounds, UINT texture);
void render_uninit(void);
void render_unit_line(int dimension);
BOOL render_unproject(float x, float y, float z,
                      const bounds_type* bounds,
                      const float model[16], const float projection[16],
                      float* view_x, float* view_y, float* view_z);
void render_update(float secs);
void render_x(const bounds_type* bounds);

/**************************************************************************
* Function Implementations
**************************************************************************/


#ifdef __cplusplus
}
#endif

#endif
